package com.deschen.security.core.social.qq.api;

import com.deschen.security.core.social.qq.api.QQ;
import com.deschen.security.core.social.qq.api.QQUserInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.oauth1.AbstractOAuth1ApiBinding;
import org.springframework.social.oauth2.AbstractOAuth2ApiBinding;
import org.springframework.social.oauth2.TokenStrategy;

import java.io.IOException;

/**
 * @Author deschen
 * @Create 2019/9/1
 * @Description spring social第三方QQ登入中第六步获取用户信息接口实现类
 * @Since 1.0.0
 */
// 文档：https://wiki.connect.qq.com/openapi%E8%B0%83%E7%94%A8%E8%AF%B4%E6%98%8E_oauth2-0
@Slf4j
public class QQImpl extends AbstractOAuth2ApiBinding implements QQ {
    /**
     *  AbstractOAuth2ApiBinding中
     *  private final String accessToken;  final修饰，说明为每个获取用户的信息单独创建accessToken，是多例
     * 	private RestTemplate restTemplate; 发送http请求
     */


    // 获取用户信息的链接
    // PS: 没有access_token=YOUR_ACCESS_TOKEN 是因为继承AbstractOAuth2ApiBinding，里面实现其添加
    private static final String GET_USER_INFO_URL =
            "https://graph.qq.com/user/get_user_info?oauth_consumer_key=%s&openid=%s";

    // 获取OpenId链接
    private static final String GET_OPEN_ID_URL =
            "https://graph.qq.com/oauth2.0/me?access_token=%s";


    private String appId;

    private String openId;

    private ObjectMapper objectMapper = new ObjectMapper();

    public QQImpl(String accessToken, String appId) {
        // 把accessToken放在GET_USER_INFO_URL中
        super(accessToken, TokenStrategy.ACCESS_TOKEN_PARAMETER);
        this.appId = appId;
        // 获取openId
        // 文档：https://wiki.connect.qq.com/%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7openid_oauth2-0
        String getOpenIdUrl = String.format(GET_OPEN_ID_URL, accessToken);
        String openIdResponse = getRestTemplate().getForObject(getOpenIdUrl, String.class);
        log.info("【QQ登入】获取OpenId信息 openIdResponse = {}", openIdResponse);
        this.openId = StringUtils.substringBetween(openIdResponse, "openid\":\"", "\"}");
        log.info("【QQ登入】获取OpenId信息 openId = {}", openId);
        // 忽略json转换vo缺少相应属性报错
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 获取QQ用户信息
     * https://graph.qq.com/user/get_user_info?access_token=申请到3个月有效期的令牌& -》
     * oauth_consumer_key=申请QQ登录成功后，分配给应用的appid& -》
     * openid=用户的ID，与QQ号码一一对应。
     * @return
     */
    @Override
    public QQUserInfo getQQUserInfo(){
        String getUserInfoUrl = String.format(GET_USER_INFO_URL, appId, openId);
        String userInfoResponse = getRestTemplate().getForObject(getUserInfoUrl, String.class);
        QQUserInfo qqUserInfo = null;
        try {
            qqUserInfo = objectMapper.readValue(userInfoResponse, QQUserInfo.class);
            qqUserInfo.setOpenId(openId);
        } catch (IOException e) {
            throw new RuntimeException("获取用户信息失败");
        }
        return qqUserInfo;
    }
}
